package mongo.fcl.gridfs;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

import org.bson.Document;
import org.bson.types.ObjectId;

import com.mongodb.Block;
import com.mongodb.MongoClient;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.GridFSFindIterable;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.mongodb.client.gridfs.model.GridFSUploadOptions;

/**
 * @author fang.cai.liang@aliyun.com
 * @date 2016年11月25日 上午10:43:26
 */

public class GridFSDemo {

	private static final String MONGO_SERVER_URL = "localhost:27017";
	
	private static final String DB_NAME = "gridfs"; // 数据库名不存在会自动创建
	
	private static MongoClient mongoClient = new MongoClient(MONGO_SERVER_URL);
	
	private static GridFSBucket gridFSBucket = GridFSBuckets.create(mongoClient.getDatabase(DB_NAME), "testFile1");
	
	public static void main(String[] args) throws Exception {
		

		// insert();
		
		//search();
		
		ObjectId fileId = new ObjectId("5837b139054ebc24e5ae35a8");
		
		//download(fileId, "/Users/fangcailiang/Downloads/lemon2.sql");
		
		//System.out.println(download(fileId));
		
		//System.out.println(download("lemon"));
		
		
//		rename(new ObjectId("5837b27b054ebc25068ac00a"), "ideaIU-2016.1.3_V1");
//		search();
		
		search();
		delete(new ObjectId("5837b27b054ebc25068ac00a"));
		search();
		
	}
	
	public static void insert() throws FileNotFoundException {
		
//		InputStream inputStream = new FileInputStream(new File("/Users/fangcailiang/Downloads/lemon.sql"));
//		GridFSUploadOptions gridFSUploadOptions = new GridFSUploadOptions();
//		gridFSUploadOptions.chunkSizeBytes(1024); 
//		gridFSUploadOptions.metadata(new Document("type", "sql"));  
//
//        ObjectId fileId = gridFSBucket.uploadFromStream("lemon", inputStream, gridFSUploadOptions);  
		
        
		InputStream inputStream = new FileInputStream(new File("/Users/fangcailiang/Downloads/ideaIU-2016.1.3.dmg"));
		GridFSUploadOptions gridFSUploadOptions = new GridFSUploadOptions();
		gridFSUploadOptions.chunkSizeBytes(10240); // 将文件切分成多块，每一块的大小，这里每一块是 10K
		gridFSUploadOptions.metadata(new Document("type", "exe"));  

        ObjectId fileId = gridFSBucket.uploadFromStream("ideaIU-2016.1.3_v2", inputStream, gridFSUploadOptions); 
		
        System.out.println(fileId);
        
        mongoClient.close();
	}
	
	public static void search(){
		//GridFSFindIterable iterable = gridFSBucket.find(Filters.eq("metadata.type", "exe"));
		GridFSFindIterable iterable = gridFSBucket.find(); // 查询出所有文件
		Block<GridFSFile> block = new Block<GridFSFile>() {
			@Override
             public void apply(final GridFSFile gridFSFile) {  
                 System.out.println(gridFSFile.getId() + ": " + gridFSFile.getFilename());
             }  
         };
		iterable.forEach(block);
	}
	
	/**
	 * 根据文件 id 下载文件
	 * @param fileId
	 * @return
	 * @throws Exception
	 */
	public static String download(ObjectId fileId) throws Exception{
		GridFSDownloadStream downloadStream = gridFSBucket.openDownloadStream(fileId);  
		return download(downloadStream);
	}

	/**
	 * 根据文件名下载文件
	 * @param fileName
	 * @return
	 * @throws Exception
	 */
	public static String download(String fileName) throws Exception{
		GridFSDownloadStream downloadStream = gridFSBucket.openDownloadStream(fileName);  
		return download(downloadStream);
	}
	
	/**
	 * @param downloadStream
	 * @return
	 * @throws Exception
	 */
	public static String download(GridFSDownloadStream downloadStream) throws Exception{
		int fileLength = (int) downloadStream.getGridFSFile().getLength(); // 获取文件的总大小
        int chunkSize = downloadStream.getGridFSFile().getChunkSize(); // 获取每一块的大小
        byte[] bytesToWriteTo = new byte[Math.min(fileLength, chunkSize)];
        int count = (fileLength/chunkSize) + 1; // 计算文件一共被分了多少块
        StringBuilder stringBuilder = new StringBuilder();
        for(int i = 0; i < count; i ++){  
        	downloadStream.read(bytesToWriteTo);
        	stringBuilder.append(new String(bytesToWriteTo, StandardCharsets.UTF_8));
        }
        return stringBuilder.toString();
	}
	
	/**
	 * 这种方法只会下载 第一个分块
	 * @param fileId
	 * @param path
	 * @throws Exception
	 */
	public static void download(ObjectId fileId, String path) throws Exception{
		FileOutputStream streamToDownloadTo = new FileOutputStream(path);  
        gridFSBucket.downloadToStream(fileId, streamToDownloadTo);  
        streamToDownloadTo.close();
	}
	
	/**
	 * 对文件重命名
	 * @param fileId
	 * @param newFilename
	 */
	public static void rename(ObjectId fileId, String newFilename){
		gridFSBucket.rename(fileId, newFilename);
	}
	
	/**
	 * 根据文件 id 删除文件
	 * @param fileId
	 */
	public static void delete(ObjectId fileId){
		gridFSBucket.delete(fileId);
	}
}
